package pl.wroc.pwr.mss.server.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.blinkenlights.jid3.ID3Exception;
import org.blinkenlights.jid3.MP3File;
import org.blinkenlights.jid3.v1.ID3V1Tag;
import org.blinkenlights.jid3.v1.ID3V1_1Tag;
import org.blinkenlights.jid3.v2.ID3V2Tag;
import org.blinkenlights.jid3.v2.ID3V2_3_0Tag;

import pl.wroc.pwr.mss.logic.domain.Song;
import pl.wroc.pwr.mss.server.service.SongService;

/**
 * Serwerowa implementacja serwisu dla encji Song.
 * 
 * @author mjagus
 */
public class SongServiceServerImpl extends GenericServiceImpl<Song, Long> implements SongService
{
    /**
     * Logger tej klasy.
     */
    private static final Logger log = Logger.getLogger(SongServiceServerImpl.class);

    @Override
    public Song createSongForFile(File file)
    {
        Song song = null;

        try {
            AudioFileFormat format = AudioSystem.getAudioFileFormat(file);
            Map<String, Object> properties = format.properties();
            song = new Song();

            long duration = (Long)properties.get("duration");
            song.setDuration(duration / 1000000);
            song.setFileName(file.getName());
            song.setFilePath(file.getPath());

            MP3File mp3 = new MP3File(file);
            ID3V2Tag tag = mp3.getID3V2Tag();
            if(tag != null)
            {
                song.setAlbum(tag.getAlbum());
                song.setArtist(tag.getArtist());
                song.setGenre(tag.getGenre().toString());
                song.setTrackNo(tag.getTrackNumber());
                song.setTitle(tag.getTitle());
            }
            else
            {
                ID3V1Tag tagv1 = mp3.getID3V1Tag();
                if(tagv1 != null)
                {
                    song.setAlbum(tagv1.getAlbum());
                    song.setArtist(tagv1.getArtist());
                    song.setGenre(tagv1.getGenre().toString());
                    if(tagv1 instanceof ID3V1_1Tag)
                        song.setTrackNo(((ID3V1_1Tag)tagv1).getAlbumTrack());
                    song.setTitle(tagv1.getTitle());
                }
                else
                    song.setTitle(FilenameUtils.removeExtension(file.getName()));
            }
        } catch(IOException e) {
            log.warn("I/O exception in file: " + file.getPath(), e);
            song = null;
        } catch(UnsupportedAudioFileException e) {
            log.warn("Unsupported audio format in file: " + file.getPath(), e);
            song = null;
        } catch(ID3Exception e) {
            log.warn("ID3Exception in file: " + file.getPath(), e);
            song = null;
        }

        return song;
    }

    @Override
    public List<Song> createSongsForFiles(File[] files)
    {
        List<Song> songs = new ArrayList<Song>();

        for(File file : files)
        {
            Song song = createSongForFile(file);
            if(song != null)
            {
                log.info("Adding song: " + song.getTitle());
                song.setPriority(songs.size());
                songs.add(song);
            }
        }

        return songs;
    }

    @Override
    public void updateID3Tags(Song song)
    {
        MP3File mp3 = new MP3File(new File(song.getFilePath()));

        try {
            ID3V2Tag tag = mp3.getID3V2Tag();
            if(tag == null)
                tag = new ID3V2_3_0Tag();

            if(StringUtils.isNotBlank(song.getAlbum()))
                tag.setAlbum(song.getAlbum());
            else
                tag.setAlbum("");

            if(song.getTrackNo() != null)
                tag.setTrackNumber(song.getTrackNo());

            if(StringUtils.isNotBlank(song.getArtist()))
                tag.setArtist(song.getArtist());
            else
                tag.setArtist("");

            if(StringUtils.isNotBlank(song.getTitle()))
                tag.setTitle(song.getTitle());
            else
                tag.setTitle("");

            mp3.setID3Tag(tag);
            mp3.sync();
        } catch(ID3Exception e) {
            log.error("ID3Exception when reading file: " + song.getFilePath(), e);
        }
    }
}
